home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource4
/
247_01
/
bnflsh1.c
< prev
next >
Wrap
Text File
|
1989-04-19
|
4KB
|
200 lines
/*
* MIRACL flash roots and powers
* bnflsh1.c
*/
#include <stdio.h>
#include <math.h>
#include "miracl.h"
/* Access global variables */
extern int depth; /* error tracing .. */
extern int trace[]; /* ... mechanism */
extern int nib; /* length of bigs */
extern int lg2b; /* no. bits in base */
extern small base; /* number base */
extern int workprec;
extern int stprec; /* start precision */
extern big w7,w8,w9,w10,w15; /* workspace variables */
static int RS,RD;
int quad(w,n)
big w;
int n;
{ /* generator for C.F. of square root of small integer */
static int v,u,ud,vd,a,oldn;
int t;
if (n==0)
{
u=2*RD;
ud=u;
v=1;
vd=RS;
a=RD;
if (a>=TOOBIG)
{
convert(a,w);
return TOOBIG;
}
return a;
}
else if (n==oldn) return a;
t=v;
v=a*(ud-u)+vd;
vd=t;
a=u/v;
ud=u;
u=2*RD-u%v;
oldn=n;
if (a>=TOOBIG)
{
convert(a,w);
return TOOBIG;
}
return a;
}
void fpower(x,n,w)
flash x,w;
int n;
{ /* raise floating-slash number to integer power w=x^n */
copy(x,w8);
zero(w);
if (ERNUM || size(w8)==0) return;
convert(1,w);
if (n==0) return;
depth++;
trace[depth]=51;
if (TRACER) track();
if (n<0)
{
n=(-n);
frecip(w8,w8);
}
if (n==1)
{
copy(w8,w);
depth--;
return;
}
forever
{
if (n%2!=0) fmul(w,w8,w);
n/=2;
if (ERNUM || n==0) break;
fmul(w8,w8,w8);
}
depth--;
}
bool froot(x,n,w)
flash w,x;
int n;
{ /* extract nth root of x - w=x^(1/n) using Newtons method */
bool minus,rn,rm,hack;
int nm,dn,s,op[5];
copy(x,w);
if (ERNUM || n==1) return TRUE;
if (n==(-1))
{
frecip(w,w);
return TRUE;
}
depth++;
trace[depth]=52;
if (TRACER) track();
minus=FALSE;
if (n<0)
{
minus=TRUE;
n=(-n);
}
s=exsign(w);
if (n%2==0 && s==MINUS)
{
berror(9);
depth--;
return FALSE;
}
insign(PLUS,w);
numer(w,w8);
denom(w,w9);
rn=root(w8,n,w8);
rm=root(w9,n,w9);
if (rn && rm)
{
fpack(w8,w9,w);
if (minus) frecip(w,w);
insign(s,w);
depth--;
return TRUE;
}
nm=size(w8);
dn=size(w9);
if (n==2 && ((nm<TOOBIG) || rn) && ((dn<TOOBIG) || rm))
{
if (!rn && nm<TOOBIG)
{
multiply(w8,w8,w8);
numer(w,w7);
subtract(w7,w8,w8);
RS=w8[1]+base*w8[2];
RD=nm;
build(w8,quad);
}
if (!rm && dn<TOOBIG)
{
multiply(w9,w9,w9);
denom(w,w7);
subtract(w7,w9,w9);
RS=w9[1]+base*w9[2];
RD=dn;
build(w9,quad);
}
if (size(w9)==1) copy(w8,w);
else fdiv(w8,w9,w);
if (minus) frecip(w,w);
insign(s,w);
depth--;
return FALSE;
}
hack=FALSE;
if (lent(w)<=2)
{ /* for 'simple' w only */
hack=TRUE;
fpi(w15);
fpmul(w15,1,3,w10);
fpower(w10,n,w10);
fmul(w,w10,w);
}
op[0]=0x6C; /* set up for [(n-1).x+y]/n */
op[1]=n-1;
op[2]=1;
op[3]=n;
op[4]=0;
workprec=stprec;
dconv(pow(fdsize(w),1.0/(double)n),w10);
while (workprec!=nib)
{ /* Newtons iteration w10=(w/w10^(n-1)+(n-1)*w10)/n */
if (workprec<nib) workprec*=2;
if (workprec>=nib) workprec=nib;
else if (workprec*2>nib) workprec=(nib+1)/2;
fpower(w10,n-1,w9);
fdiv(w,w9,w9);
flop(w10,w9,op,w10);
}
copy(w10,w);
op[0]=0x48;
op[1]=3;
op[3]=1;
op[2]=op[4]=0;
if (hack) flop(w,w15,op,w);
if (minus) frecip(w,w);
insign(s,w);
depth--;
return FALSE;
}